/*
 * Copyright 2011 Luis Atencio
 * 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.rt.bind;

import java.util.Map;

import net.rt.io.Strategy;
import net.rt.io.file.PropertyFileStrategy;
import net.rt.io.file.XMLFileStrategy;
import net.rt.meta.Configurable;

/**
 * Property Binder class.
 * 
 * @author Luis Atencio
 *
 */
public class PropertyBinder {

	public static <T> T bind(Class<T> clazz) {
		
		if(!clazz.isInterface()) {
			throw new IllegalArgumentException("Class instance provided must be an Interface class.");
		}
		
		// Reflect on type for @Configurable annotation
		Configurable atConfigurable = clazz.getAnnotation(Configurable.class);
		
		if(atConfigurable == null) {
			throw new IllegalArgumentException("Interface must declare the @Configurable annotation. " +
					"Properties were not bound");
		}
		
		String name = atConfigurable.name();
		String path = atConfigurable.path();
		Strategy strategy = null;
		switch(atConfigurable.strategy()) {
			
			case PROPERTY: {	
				strategy = new PropertyFileStrategy(path, name);
				break;
			}
			case XML: {
				strategy = new XMLFileStrategy(path, name);
				break;
			}
			default: 
				throw new RuntimeException("Strategy has not been implemented!");
		}
		
		// contains all file key-value pairs
		Map<String, String> map = strategy.bindProperties();
		
		// Create a proxy of the same type as the provided class<T> and 
		// intercept the methods calls to return values
		return DynamicProxy.newInstance(clazz, map);
	}
}
